﻿using LitJson;
using NCmd;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using UnityEngine;

/// <summary>
/// --------------------------------
/// |4字节消息包的头部          | 消息体json  10
/// |，这条消息一共占多少字节 14|
/// </summary>
/// <summary>
/// 消息包
/// </summary>
public class Package : Singleton<Package>
{
    public static int HEAD_LENGTH = 4;

    // 消息总长度（包含包头），以字节为单位
    public int TotalBytesLen;
    public byte[] Message;
    public int MessageLength;

    // 读包，读完后调用回调
    private int readOne(Stream dataStream)
    {
        // 非截断包，读一个包
        byte[] headBuffer = new byte[HEAD_LENGTH];
        dataStream.Read(headBuffer, 0, HEAD_LENGTH);
        var packageLength = BitConverter.ToInt32(headBuffer, 0);
        var msgLength = packageLength - HEAD_LENGTH;
        // 判断心跳包？
        if (packageLength <= 0)
        {
            return HEAD_LENGTH;
        }
        if (msgLength > dataStream.RemainingBytes()) { return -1; }

        TotalBytesLen = packageLength;
        Message = new byte[msgLength];
        MessageLength = dataStream.Read(Message, 0, Message.Length);

        return TotalBytesLen;
    }
    // 把消息组成一个包
    public byte[] Write(Cmd cmd)
    {
        var cmdStr = JsonMapper.ToJson(cmd);

        var buffer = Encoding.UTF8.GetBytes(cmdStr);
        byte[] b = BitConverter.GetBytes(buffer.Length + 4); // 包头4字节，就一个包长度

        return CopyToBig(b, buffer);
    }

    public void Read(Stream dataStream, IClient client)
    {
        // 只取完整消息包，被截断的下次再读
        // 剩余长度等于包头，是心跳包
        while (dataStream.RemainingBytes() >= Package.HEAD_LENGTH)
        {
            var ret = readOne(dataStream);
            if (ret < 0) { break; } // 只可能是最后一个包不完整

            var data = Encoding.UTF8.GetString(Message, 0, MessageLength);
            var cmdBase = JsonMapper.ToObject<NCmd.Cmd>(data);
            //Debug.Log("<color=Aquamarine>[client recive]</color>" + data);
            //Utils.LogWithColor(data, "[recive package]", "Aquamarine");

            var reader = new JsonReader(data);
            Cmd cmd = JsonMapper.ReadValue(Type.GetType(cmdBase.ClassName), reader) as Cmd;

            // 客户端收到消息
            client.ReciveCmd(cmd);
        }
    }

    public byte[] CopyToBig(byte[] bBig, byte[] bSmall)
    {
        List<byte> lTemp = new List<byte>();
        lTemp.AddRange(bBig);
        lTemp.AddRange(bSmall);
        bBig = new byte[lTemp.Count];
        lTemp.CopyTo(bBig);
        return bBig;
    }
}